<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="Content-Language" content="en">
    <meta name="color-scheme" content="light dark">

    

    <meta name="author" content="SpringHan">
    <meta name="description" content="最近，我发现了一个Emacs新出现的编辑插件 meow，我看了它的README，感觉不错，但我已经是深度 evil 用户了，并且配置文件有很多，因此不好转移。但是，我看中了它的一些功能，并给我的 evil 加上了这些features.
01 - keypad mode    这个模式不止是在 meow 上有，其它一些编辑插件中也有。我实现的函数：
(defun spring/evil-keypad-execute () &#34;Execute the keypad command.&#34; (interactive) (let ((key (pcase last-input-event (120 &#34;C-x &#34;) (101 &#34;M-&#34;) (98 &#34;C-M-&#34;) (113 &#34;C-q &#34;))) tmp) (if (null key) (message &#34;[Evil]: &#39;%s&#39; prefix is not defined in keypad.&#34; (char-to-string last-input-event)) (message key) (while (not (= 13 (setq tmp (read-char)))) (if (= tmp 127) (setq key (substring key 0 -2)) (setq key (concat key (cond ((= tmp 44) &#34;C-&#34;) ((= tmp 46) &#34;M-&#34;) ((= tmp 47) &#34;C-M-&#34;) (t (concat (char-to-string tmp) &#34; &#34;)))))) (message key)) (setq key (substring key 0 -1)) (if (commandp (setq tmp (key-binding (read-kbd-macro key)))) (call-interactively tmp) (message &#34;[Evil]: &#39;%s&#39; is not defined.">
    <meta name="keywords" content="developer,emacs">

    <meta name="twitter:card" content="summary"/>
<meta name="twitter:title" content="Evil 技巧"/>
<meta name="twitter:description" content="最近，我发现了一个Emacs新出现的编辑插件 meow，我看了它的README，感觉不错，但我已经是深度 evil 用户了，并且配置文件有很多，因此不好转移。但是，我看中了它的一些功能，并给我的 evil 加上了这些features.
01 - keypad mode    这个模式不止是在 meow 上有，其它一些编辑插件中也有。我实现的函数：
(defun spring/evil-keypad-execute () &#34;Execute the keypad command.&#34; (interactive) (let ((key (pcase last-input-event (120 &#34;C-x &#34;) (101 &#34;M-&#34;) (98 &#34;C-M-&#34;) (113 &#34;C-q &#34;))) tmp) (if (null key) (message &#34;[Evil]: &#39;%s&#39; prefix is not defined in keypad.&#34; (char-to-string last-input-event)) (message key) (while (not (= 13 (setq tmp (read-char)))) (if (= tmp 127) (setq key (substring key 0 -2)) (setq key (concat key (cond ((= tmp 44) &#34;C-&#34;) ((= tmp 46) &#34;M-&#34;) ((= tmp 47) &#34;C-M-&#34;) (t (concat (char-to-string tmp) &#34; &#34;)))))) (message key)) (setq key (substring key 0 -1)) (if (commandp (setq tmp (key-binding (read-kbd-macro key)))) (call-interactively tmp) (message &#34;[Evil]: &#39;%s&#39; is not defined."/>

    <meta property="og:title" content="Evil 技巧" />
<meta property="og:description" content="最近，我发现了一个Emacs新出现的编辑插件 meow，我看了它的README，感觉不错，但我已经是深度 evil 用户了，并且配置文件有很多，因此不好转移。但是，我看中了它的一些功能，并给我的 evil 加上了这些features.
01 - keypad mode    这个模式不止是在 meow 上有，其它一些编辑插件中也有。我实现的函数：
(defun spring/evil-keypad-execute () &#34;Execute the keypad command.&#34; (interactive) (let ((key (pcase last-input-event (120 &#34;C-x &#34;) (101 &#34;M-&#34;) (98 &#34;C-M-&#34;) (113 &#34;C-q &#34;))) tmp) (if (null key) (message &#34;[Evil]: &#39;%s&#39; prefix is not defined in keypad.&#34; (char-to-string last-input-event)) (message key) (while (not (= 13 (setq tmp (read-char)))) (if (= tmp 127) (setq key (substring key 0 -2)) (setq key (concat key (cond ((= tmp 44) &#34;C-&#34;) ((= tmp 46) &#34;M-&#34;) ((= tmp 47) &#34;C-M-&#34;) (t (concat (char-to-string tmp) &#34; &#34;)))))) (message key)) (setq key (substring key 0 -1)) (if (commandp (setq tmp (key-binding (read-kbd-macro key)))) (call-interactively tmp) (message &#34;[Evil]: &#39;%s&#39; is not defined." />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://springhan.gitee.io/blog/emacs/evil-skill/" /><meta property="article:section" content="emacs" />
<meta property="article:published_time" content="2021-01-02T10:47:24&#43;08:00" />
<meta property="article:modified_time" content="2021-01-02T10:47:24&#43;08:00" />



    <title>
  Evil 技巧 · SpringHan Blog
</title>

    
      <link rel="canonical" href="https://springhan.gitee.io/blog/emacs/evil-skill/">
    

    <link rel="preload" href="/fonts/forkawesome-webfont.woff2?v=1.1.7" as="font" type="font/woff2" crossorigin>

    
      
      
      <link rel="stylesheet" href="/blog/css/coder.min.04d6bedce375c4fcb6bf1e2c89e70f9e45a3431f1926a9f5f63749517718d366.css" integrity="sha256-BNa&#43;3ON1xPy2vx4siecPnkWjQx8ZJqn19jdJUXcY02Y=" crossorigin="anonymous" media="screen" />
    

    

    
      
        
        
        <link rel="stylesheet" href="/blog/css/coder-dark.min.dde8a61eb31a32353b4baf3d9113f03c4ea2a8ca9bb736f59ca2d2b2cb664f0b.css" integrity="sha256-3eimHrMaMjU7S689kRPwPE6iqMqbtzb1nKLSsstmTws=" crossorigin="anonymous" media="screen" />
      
    

    

    

    <link rel="icon" type="image/png" href="/blog/img/favicon-32x32.png" sizes="32x32">
    <link rel="icon" type="image/png" href="/blog/img/favicon-16x16.png" sizes="16x16">

    <link rel="apple-touch-icon" href="/blog/images/apple-touch-icon.png">
    <link rel="apple-touch-icon" sizes="180x180" href="/blog/images/apple-touch-icon.png">

    
      <script defer src="https://twemoji.maxcdn.com/v/13.0.2/twemoji.min.js"
        integrity="sha384-wyB/MspSJ/r2bT2kCj44qtsYRYlpzO2oAPhRj5myrWD63dt6qWv4x8AZe7Fl3K3b" crossorigin="anonymous"></script>
    

    <meta name="generator" content="Hugo 0.82.0" />
  </head>

  
  
    
  
  <body class="preload-transitions colorscheme-auto"
        onload=" twemoji.parse(document.body); "
  >
    
<div class="float-container">
    <a id="dark-mode-toggle" class="colorscheme-toggle">
        <i class="fa fa-adjust fa-fw" aria-hidden="true"></i>
    </a>
</div>


    <main class="wrapper">
      <nav class="navigation">
  <section class="container">
    <a class="navigation-title" href="/blog">
      SpringHan Blog
    </a>
    
      <input type="checkbox" id="menu-toggle" />
      <label class="menu-button float-right" for="menu-toggle">
        <i class="fa fa-bars fa-fw" aria-hidden="true"></i>
      </label>
      <ul class="navigation-list">
        
          
            <li class="navigation-item">
              <a class="navigation-link" href="/blog/emacs/">Emacs</a>
            </li>
          
        
        
      </ul>
    
  </section>
</nav>


      <div class="content">
        
  <section class="container page">
  <article>
    <header>
      <h1 class="title">
        <a class="title-link" href="https://springhan.gitee.io/blog/emacs/evil-skill/">
          Evil 技巧
        </a>
      </h1>
    </header>

    <p>最近，我发现了一个Emacs新出现的编辑插件 <code>meow</code>，我看了它的README，感觉不错，但我已经是深度 <code>evil</code> 用户了，并且配置文件有很多，因此不好转移。但是，我看中了它的一些功能，并给我的 <code>evil</code> 加上了这些features.</p>
<h2 id="01---keypad-mode">
  01 - keypad mode
  <a class="heading-link" href="#01---keypad-mode">
    <i class="fa fa-link" aria-hidden="true"></i>
  </a>
</h2>
<p>这个模式不止是在 <code>meow</code> 上有，其它一些编辑插件中也有。我实现的函数：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(defun spring/evil-keypad-execute ()
  <span style="color:#e6db74">&#34;Execute the keypad command.&#34;</span>
  (interactive)
  (let ((key (pcase last-input-event
               (<span style="color:#ae81ff">120</span> <span style="color:#e6db74">&#34;C-x &#34;</span>) (<span style="color:#ae81ff">101</span> <span style="color:#e6db74">&#34;M-&#34;</span>) (<span style="color:#ae81ff">98</span> <span style="color:#e6db74">&#34;C-M-&#34;</span>) (<span style="color:#ae81ff">113</span> <span style="color:#e6db74">&#34;C-q &#34;</span>)))
        tmp)
    (if (<span style="color:#a6e22e">null</span> key)
        (<span style="color:#a6e22e">message</span> <span style="color:#e6db74">&#34;[Evil]: &#39;%s&#39; prefix is not defined in keypad.&#34;</span>
                 (<span style="color:#a6e22e">char-to-string</span> last-input-event))
      (<span style="color:#a6e22e">message</span> key)
      (while (not (<span style="color:#a6e22e">=</span> <span style="color:#ae81ff">13</span> (setq tmp (<span style="color:#a6e22e">read-char</span>))))
        (if (<span style="color:#a6e22e">=</span> tmp <span style="color:#ae81ff">127</span>)
            (setq key (<span style="color:#a6e22e">substring</span> key <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">-2</span>))
          (setq key (<span style="color:#a6e22e">concat</span> key
                            (cond ((<span style="color:#a6e22e">=</span> tmp <span style="color:#ae81ff">44</span>) <span style="color:#e6db74">&#34;C-&#34;</span>)
                                  ((<span style="color:#a6e22e">=</span> tmp <span style="color:#ae81ff">46</span>) <span style="color:#e6db74">&#34;M-&#34;</span>)
                                  ((<span style="color:#a6e22e">=</span> tmp <span style="color:#ae81ff">47</span>) <span style="color:#e6db74">&#34;C-M-&#34;</span>)
                                  (<span style="color:#66d9ef">t</span> (<span style="color:#a6e22e">concat</span> (<span style="color:#a6e22e">char-to-string</span> tmp) <span style="color:#e6db74">&#34; &#34;</span>))))))
        (<span style="color:#a6e22e">message</span> key))
      (setq key (<span style="color:#a6e22e">substring</span> key <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">-1</span>))
      (if (<span style="color:#a6e22e">commandp</span> (setq tmp (<span style="color:#a6e22e">key-binding</span> (read-kbd-macro key))))
          (<span style="color:#a6e22e">call-interactively</span> tmp)
        (<span style="color:#a6e22e">message</span> <span style="color:#e6db74">&#34;[Evil]: &#39;%s&#39; is not defined.&#34;</span> key)))))

<span style="color:#75715e">;; Keybinding</span>
(evil-leader/set-key
  <span style="color:#75715e">;; ...</span>
  <span style="color:#e6db74">&#34;x&#34;</span> <span style="color:#e6db74">&#39;spring/evil-keypad-execute</span>
  <span style="color:#e6db74">&#34;e&#34;</span> <span style="color:#e6db74">&#39;spring/evil-keypad-execute</span>
  <span style="color:#e6db74">&#34;b&#34;</span> <span style="color:#e6db74">&#39;spring/evil-keypad-execute</span>
  <span style="color:#e6db74">&#34;q&#34;</span> <span style="color:#e6db74">&#39;spring/evil-keypad-execute</span>
  <span style="color:#75715e">;;...</span>
  )
</code></pre></div><p>通过这个函数，我可以很方便地使用 <code>,-(x/e/b/q)</code> 来模拟 <code>C-x</code>/<code>M-</code>/<code>C-M-</code>/<code>C-q</code> 这些按键，大大解放了手指。并且在输入时可以用 <code>,</code>/<code>.</code>/<code>/</code> 来代替 <code>C-</code>/<code>M-</code>/<code>C-M-</code>，还可以用 <code>DEL</code> 来删除上一个指令键。</p>
<h2 id="10---使用中间键盘代替数字键使用-digit-argument">
  10 - 使用中间键盘代替数字键使用 <code>digit-argument</code>
  <a class="heading-link" href="#10---%e4%bd%bf%e7%94%a8%e4%b8%ad%e9%97%b4%e9%94%ae%e7%9b%98%e4%bb%a3%e6%9b%bf%e6%95%b0%e5%ad%97%e9%94%ae%e4%bd%bf%e7%94%a8-digit-argument">
    <i class="fa fa-link" aria-hidden="true"></i>
  </a>
</h2>
<p>这个功能并不存在于 <code>meow</code>，但我从它的源码中有所学习，知道了 <code>digit-argument</code> 这个函数(之前我一直想实现但不知道怎么实现)。<a href="https://emacs-china.org/t/topic/15679/74?u=springhan">对于这个功能，我也对meow开发者提出了建议</a><br>
源码：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(defun spring/arg-with-middle-keyboard (<span style="color:#66d9ef">&amp;optional</span> msg)
  <span style="color:#e6db74">&#34;A function which make you can use the middle of the keyboard instead of the num keyboard.&#34;</span>
  (interactive)
  (let ((number <span style="color:#e6db74">&#34;&#34;</span>)
        (arg <span style="color:#e6db74">&#34;&#34;</span>))
    (while (not (string= number <span style="color:#e6db74">&#34;over&#34;</span>))
      (setq number
            (pcase (<span style="color:#a6e22e">read-char</span>)
              (<span style="color:#ae81ff">97</span> <span style="color:#e6db74">&#34;1&#34;</span>) (<span style="color:#ae81ff">114</span> <span style="color:#e6db74">&#34;2&#34;</span>) (<span style="color:#ae81ff">115</span> <span style="color:#e6db74">&#34;3&#34;</span>) (<span style="color:#ae81ff">116</span> <span style="color:#e6db74">&#34;4&#34;</span>) (<span style="color:#ae81ff">100</span> <span style="color:#e6db74">&#34;5&#34;</span>)
              (<span style="color:#ae81ff">104</span> <span style="color:#e6db74">&#34;6&#34;</span>) (<span style="color:#ae81ff">110</span> <span style="color:#e6db74">&#34;7&#34;</span>) (<span style="color:#ae81ff">101</span> <span style="color:#e6db74">&#34;8&#34;</span>) (<span style="color:#ae81ff">105</span> <span style="color:#e6db74">&#34;9&#34;</span>) (<span style="color:#ae81ff">111</span> <span style="color:#e6db74">&#34;0&#34;</span>)
              (<span style="color:#ae81ff">39</span> <span style="color:#e6db74">&#34;-&#34;</span>) (<span style="color:#ae81ff">13</span> <span style="color:#e6db74">&#34;over&#34;</span>) (<span style="color:#ae81ff">127</span> <span style="color:#e6db74">&#34;delete&#34;</span>)))
      (unless (string= number <span style="color:#e6db74">&#34;over&#34;</span>)
        (if (string= number <span style="color:#e6db74">&#34;delete&#34;</span>)
            (setq arg (<span style="color:#a6e22e">substring</span> arg <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">-1</span>))
          (setq arg (<span style="color:#a6e22e">concat</span> arg number))))
      (<span style="color:#a6e22e">message</span> <span style="color:#e6db74">&#34;%s%s&#34;</span> (if msg
                          msg
                        <span style="color:#e6db74">&#34;C-&#34;</span>)
               arg))
    (<span style="color:#a6e22e">string-to-number</span> arg)))

(defun spring/evil-digit-argument (arg)
  <span style="color:#e6db74">&#34;The digit argument function.&#34;</span>
  (interactive (<span style="color:#a6e22e">list</span> (spring/arg-with-middle-keyboard)))
  (prefix-command-preserve-state)
  (setq prefix-arg arg)
  (universal-argument--mode))

<span style="color:#75715e">;; (set-movement-evil-states-keys) 是我定义的绑定移动模式下全局按键的函数</span>
(set-movement-evil-states-keys (kbd <span style="color:#e6db74">&#34;SPC&#34;</span>) <span style="color:#e6db74">&#39;spring/evil-digit-argument</span>)
</code></pre></div><p>通过这个函数，我可以使用 <code>SPC</code>，然后中间一行字母键就可以当做数字键来使用了(<code>DEL</code> 用作删除上一个数字，<code>'</code>是负号)，最后按下 <code>RET</code> 即可。你如果直接使用这些代码，可能结果与我有所不同，因为我是 <a href="https://colemak.com/">Colemak</a> 用户，这套按键是完全依照 <code>Colemak</code> 键盘布局所设计的，所以你可能需要自己更改。</p>

  </article>
</section>

  

      </div>

      
  <footer class="footer">
    <section class="container">
      
      
        ©
        
          2019 -
        
        2021
         SpringHan 
      
      
         · 
        Powered by <a href="https://gohugo.io/">Hugo</a> & SpringHan.
      
      
    </section>
  </footer>


    </main>

    
      
      <script src="/blog/js/coder.min.235666b114443867d43eeb5799d51f6252965e5163f338285e113fa381d3d27e.js" integrity="sha256-I1ZmsRREOGfUPutXmdUfYlKWXlFj8zgoXhE/o4HT0n4="></script>
    

    

    

    

    

    

    

    

    
  </body>

</html>
